﻿/**
 * Copyright (C) 2004-2009 D3Systems, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using agsXMPP;
using agsXMPP.protocol.client;

namespace OMGGateways
{
    /// <summary>
    /// XMPP Gateway Module implementing the GWInterface.
    /// The current version is using AGSXMPP API which is GPL.
    /// </summary>
    public class XMPPGateway : GWInterface
    {
        /// <summary>
        /// XMPP Client Connection Object - Responsible for maintaining 
        /// and managing the connection to the XMPP backend
        /// </summary>
        XmppClientConnection xmppConn;

        /// <summary>
        /// Login Details to be used by this Gateway
        /// </summary>
        LoginDetails loginDetails;

        // Event Logger for Debugging Purposes
        /// <summary>
        /// Reference to the Event Log object used to track and debug the application.
        /// </summary>
        System.Diagnostics.EventLog logger;

        public void SetLoginDetails(LoginDetails loginDetails)
        {
            this.loginDetails = loginDetails;
        }

        /// <summary>
        /// Default Constructor
        /// </summary>
        public XMPPGateway()
        {
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        public XMPPGateway(LoginDetails loginDetails, System.Diagnostics.EventLog logger)
        {

            Init(loginDetails, logger);

        }

        /// <summary>
        /// Inisitialize the Connections and other pertinent details
        /// </summary>
        /// <param name="loginDetails"></param>
        /// <param name="logger"></param>
        public void Init(LoginDetails loginDetails, System.Diagnostics.EventLog logger)
        {
            this.logger = logger;

            this.loginDetails = loginDetails;

            xmppConn = new XmppClientConnection(loginDetails.Domain, loginDetails.Port);

            xmppConn.OnLogin += new ObjectHandler(OnLogin);

            xmppConn.OnRosterStart += new ObjectHandler(OnRosterStart);
            xmppConn.OnRosterItem += new agsXMPP.XmppClientConnection.RosterHandler(OnRosterItem);
            xmppConn.OnRosterEnd += new ObjectHandler(OnRosterEnd);

            xmppConn.OnPresence += new PresenceHandler(OnPresence);
            xmppConn.OnMessage += new MessageHandler(OnMessage);

            xmppConn.OnClose += new ObjectHandler(OnClose);

            xmppConn.OnAuthError += new XmppElementHandler(OnAuthError);
        }

        /// <summary>
        /// Implementation of GWInterface - Login to the XMPP Server
        /// </summary>
        /// <param name="username">Username of the XMPP user.</param>
        /// <param name="password">Password of the XMPP user.</param>
        public void Login()
        {
            logger.WriteEntry("Logging in ...");
            
            xmppConn.Open(loginDetails.Username, loginDetails.Password, "OMG");            
        }

        /// <summary>
        /// Implementation of GWInterface - Send a Message to a User
        /// </summary>
        /// <param name="toJid">JID of the receiver</param>
        /// <param name="type">Message Type</param>
        /// <param name="body">The content of the message.</param>
        public void SendMessage(Jid toJid, MessageType type, String body)
        {
            xmppConn.Send(new Message(toJid, type, body));
        }

        /// <summary>
        /// Implementation of GWInterface - Send Presence to all subscribed contacts
        /// </summary>
        /// <param name="type"></param>
        /// <param name="status"></param>
        public void SendPresence(ShowType type, String status)
        {
            xmppConn.Show = type;
            xmppConn.Status = status;
            xmppConn.SendMyPresence();
        }

        // --------------- OBJECT HANDLERS ------------------
        /// <summary>
        /// Object Handler method to handle the Login Events.
        /// </summary>
        /// <param name="sender"></param>
        private void OnLogin(object sender)
        {
            if (xmppConn != null && xmppConn.Authenticated)
            {
                //xmppConn.Show = ShowType.NONE;
                //xmppConn.SendMyPresence();

                SendPresence(ShowType.NONE, "");
            }
        }

        /// <summary>
        /// Object Handler method to handle the Start of a Roster Event
        /// </summary>
        /// <param name="sender"></param>
        private void OnRosterStart(object sender)
        {
            logger.WriteEntry("Roster Retrieval STARTED");
        }

        /// <summary>
        /// Object Handler method to handle the End of a Roster Event
        /// </summary>
        /// <param name="sender"></param>
        private void OnRosterEnd(object sender)
        {
            logger.WriteEntry("Roster Retrieval ENDED");
        }

        /// <summary>
        /// Object Handler method to handle Roster Item Events.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="item"></param>
        private void OnRosterItem(object sender, agsXMPP.protocol.iq.roster.RosterItem item)
        {
            String userId = item.Jid.User;
            String name = item.Name;
            String subs = item.Subscription.ToString();

            logger.WriteEntry("Roster Item Received: " + userId + " - " + name + " - " + subs);
        }

        /// <summary>
        /// Object Handler method to Handle Presence Events.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="presence"></param>
        private void OnPresence(object sender, Presence presence)
        {
            String userId = presence.From.User;
            String status = presence.Status;

            logger.WriteEntry("Presence Received: " + userId + " - " + status);
        }

        /// <summary>
        /// Object Handler method to Handle Message Events
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="msg"></param>
        private void OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {
            String fromUser = msg.From.User;
            String toUser = msg.To.User;
            String body = msg.Body;
            MessageType type = msg.Type;

            logger.WriteEntry("Message (" + type.ToString() + ") received: From (" + fromUser + ") To (" + toUser + ") - " + body );
        }

        /// <summary>
        /// Object Handler method to Handle the Close Events
        /// </summary>
        /// <param name="sender"></param>
        private void OnClose(object sender)
        {
            logger.WriteEntry("Something has closed ...");
        }

        /// <summary>
        /// Object Handler method Handle Authorization Error
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAuthError(object sender, agsXMPP.Xml.Dom.Element e)
        {
            logger.WriteEntry("Authorization Error ...");
        }
    }
}
